package com.wubo.sec;


import java.util.Collection;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.authentication.encoding.ShaPasswordEncoder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import com.wubo.sec.core.UserData;
import com.wubo.sec.event.LogEvent;
import com.wubo.sec.log.ILog;
import com.wubo.sec.model.Authority;
import com.wubo.sec.model.Group;

/**
 * 安全管理器
 * @author WuBo
 * @CreateDate 2012-1-18
 */
public class SecurityManager implements ApplicationEventPublisherAware {
	private static ApplicationEventPublisher eventPublisher;
	
	private static PasswordEncoder passwordEncoder;
	
	static {
		passwordEncoder = new ShaPasswordEncoder();
		((ShaPasswordEncoder)passwordEncoder).setEncodeHashAsBase64(true);
	}
	/**
	 * 发布事件
	 * @param event
	 */
	public static void publishEvent(ApplicationEvent event){
		eventPublisher.publishEvent(event);
	}
	/**
	 * 得到当前用户
	 * @return
	 */
	public static UserData getCurrentUser(){
		if(SecurityContextHolder.getContext().getAuthentication() == null){
			return null;
		}
		Object user = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		
		if(user instanceof UserData){
			return (UserData) user;
		}
		return null;
	}
	/**
	 * 指定用户是否拥有管理员权限
	 * @param user
	 * @return
	 */
	public static boolean hasAdminAuth(UserData user){
		if(user ==  null)return false;
		Collection<? extends GrantedAuthority> authSet = user.getAuthorities();
		for(GrantedAuthority a : authSet){
			if(Authority.ADMIN.equals(a.getAuthority())){
				return true;
			}
		}
		return false;
	}
	/**
	 * 指定用户是否拥有指定的权限
	 * @param user
	 * @param auth
	 * @return
	 */
	public static boolean hasAuth(UserData user, String auth){
		if(user ==  null || auth == null)return false;
		Collection<? extends GrantedAuthority> authSet = user.getAuthorities();
		for(GrantedAuthority a : authSet){
			if(auth.equals(a.getAuthority())){
				return true;
			}
		}
		return false;
	}
	/**
	 * 指定用户是否拥有指定的几个权限
	 * @param user
	 * @param auths
	 * @return
	 */
	public static boolean hasAllAuth(UserData user, String[] auths){
		if(user ==  null || auths == null || auths.length == 0)return false;
		Collection<? extends GrantedAuthority> authSet = user.getAuthorities();
		int l = 0;
		for(String auth : auths){
			for(GrantedAuthority a : authSet){
				if(auth.equals(a.getAuthority())){
					l++;
					break;
				}
			}
		}
		return l == auths.length;
	}
	/**
	 * 指定用户是否拥有指定的几个权限中的任意一个
	 * @param user
	 * @param auths
	 * @return
	 */
	public static boolean hasAnyAuth(UserData user, String[] auths){
		if(user ==  null || auths == null || auths.length == 0)return false;
		Collection<? extends GrantedAuthority> authSet = user.getAuthorities();
		for(String auth : auths){
			for(GrantedAuthority a : authSet){
				if(auth.equals(a.getAuthority())){
					return true;
				}
			}
		}
		return false;
	}
	/**
	 * 判断是否为管理员（注意：有管理员权限的不一定是管理员）
	 * @return
	 */
	public static boolean isAdmin(){
		return getPriorityOfCurrentUser() >= Group.SUPER;
	}
	/**
	 * 得到当前用户等级
	 * @return
	 */
	public static int getPriorityOfCurrentUser(){
		UserData u = getCurrentUser();
		if(u == null)return 0;
		return u.getGroup().getPriority();
	}
	/**
	 * 判断当前用户是否为标识锁定
	 * @return
	 */
	public static boolean isMarkLocked(){
		UserData u = getCurrentUser();
		if(u == null)return true;
		return u.getGroup().isMarkLocked();
	}
	/**
	 * 记录日志
	 * @param log
	 */
	public static void log(ILog log){
		eventPublisher.publishEvent(new LogEvent(log));
	}
	
	public void setApplicationEventPublisher(
			ApplicationEventPublisher applicationEventPublisher) {
		eventPublisher = applicationEventPublisher;
	}
	/**
	 * 为明文密码加密
	 * @param password
	 * @param salt
	 * @return
	 */
	public static String encodePassword(String password, String salt){
		return passwordEncoder.encodePassword(password, salt);
	}
}
